﻿#region header

//  ***************************************************************************
// *                                LICENSE
//  ***************************************************************************
//  * "Haplous" .NET Simple 2D Game Framework
//  * 
//  * Copyright © Jonathan Evans 2014-2014
//  * 
//  * This program is free software; you can redistribute it and/or
//  * modify it under the terms of the GNU General Public License
//  * as published by the Free Software Foundation; either version 2
//  * of the License, or (at your option) any later version.
//  * 
//  * This program is distributed in the hope that it will be useful,
//  * but WITHOUT ANY WARRANTY; without even the implied warranty of
//  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  * GNU General Public License for more details.
//  * 
//  * You should have received a copy of the GNU General Public License
//  * along with this program; if not, write to the Free Software
//  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//  * 
//  ***************************************************************************
//  * 
//  * Contact: opencollar@googlemail.com
//  * 
//  * Website: http://haplous.codeplex.com/
//  *
//  * NuGet:   http://www.nuget.org/packages/haplous/
//  *
//  * File:    Haplous/Haplous/ErrorManager.cs
//  *
//  ***************************************************************************

#endregion

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;

using Haplous.Properties;

using JetBrains.Annotations;

namespace Haplous.Core
{
    /// <summary>
    ///     Common methods for capturing and managing exceptions.
    /// </summary>
    public static class ErrorManager
    {
        /// <summary>
        ///     Occurs when an unhandled exception occurs.
        /// </summary>
        public static event EventHandler<UnhandledExceptionEventArgs> UnhandledException;

        /// <summary>
        ///     Call this method when an exception has occurred and there is no way to handle it (for example when you are in an
        ///     event handler).
        /// </summary>
        /// <param name="exception">The exception.</param>
        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public static void OnUnhandledException([NotNull] Exception exception)
        {
            if(exception == null)
                return;

            Console.ForegroundColor = ConsoleColor.Red;
            var message = string.Format(CultureInfo.CurrentCulture, Resources.Message_UnhandledException, exception.Message);
            Console.WriteLine(message);
            Debug.WriteLine(message);

            var handler = UnhandledException;
            if(handler == null)
                return;

            var callbacks = handler.GetInvocationList();
            if((callbacks == null) || (callbacks.Length <= 0))
                return;

            var args = new UnhandledExceptionEventArgs(exception);

            foreach(var callback in callbacks)
            {
                try
                {
                    Debug.Assert(callback != null, "callback != null");
                    callback.DynamicInvoke(null, args);
                }
                catch
                {
                    try
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
// ReSharper disable once AssignNullToNotNullAttribute
                        message = string.Format(CultureInfo.CurrentCulture, Resources.Message_ErrorHandlingError, exception.Message);
                        Console.WriteLine(message);
                        Debug.WriteLine(message);
                    }
// ReSharper disable once EmptyGeneralCatchClause
                    catch
                    {
                        // Ignore now.
                    }
                }
            }
        }
    }

    /// <summary>
    ///     Defines the arguments passed when the <see cref="ErrorManager.UnhandledException" /> event is raised. This class
    ///     cannot be inherited.
    /// </summary>
    public sealed class UnhandledExceptionEventArgs : EventArgs
    {
        /// <summary>
        ///     The exception that was not handled.
        /// </summary>
        [NotNull]
        private readonly Exception _exception;

        /// <summary>
        ///     Initializes a new instance of the <see cref="UnhandledExceptionEventArgs" /> class.
        /// </summary>
        /// <param name="exception">The exception that was not handled.</param>
        internal UnhandledExceptionEventArgs([NotNull] Exception exception)
        {
            _exception = exception;
        }

        /// <summary>
        ///     The exception that was not handled.
        /// </summary>
        [NotNull]
        public Exception Exception
        {
            get { return _exception; }
        }
    }
}